/*
*  This file contains several functions
*  void setup() : sets up pins
*  void printBoard(bool** board) : prints the board for testing purposes
*  bool **getBoard() : Returns a 2d array of bools representing the board
*  void loop() : Reads board then prints it with a small delay
*/

#include <stdbool.h>
#include <Arduino.h>
#include <string.h>
#include "getBoard.h"
#include "arduinoPins.h"
#include "matrixLCD.h"

extern int NUM_PIECES_LEFT;
bool myboard[8][8];

/*
 *  This function gets and returns the board state
 */
void getBoard(){
  
  int x, y;
  
  for( x = 0; x < 8; x++ ) {
    for( y = 0; y < 8; y++ ) {
      myboard[x][y] = false;
    }
  }

  //This loop scans the board
  for(x=0; x<4; x++){

    //Set select lines
    if( (x) & 0x1 ) digitalWrite(SEL_B, HIGH);
    else digitalWrite(SEL_B, LOW);		

    if( (x) & 0x2 ) digitalWrite(SEL_A, HIGH);
    else digitalWrite(SEL_A, LOW);

    //give some time for muxes to swap
    delay(20);

    //read mux outputs
    
    myboard[0][x] = (digitalRead(IN_A1) == HIGH) ? true : false;
    
    myboard[0][x+4] = (digitalRead(IN_A2) == HIGH) ? true : false;
    
    myboard[1][x] = (digitalRead(IN_B1) == HIGH) ? true : false;
    
    myboard[1][x+4] = (digitalRead(IN_B2) == HIGH) ? true : false;
     
    myboard[2][x] = (digitalRead(IN_C1) == HIGH) ? true : false;
     
    myboard[2][x+4] = (digitalRead(IN_C2) == HIGH) ? true : false;
     
    myboard[3][x] = (digitalRead(IN_D1) == HIGH) ? true : false;
     
    myboard[3][x+4] = (digitalRead(IN_D2) == HIGH) ? true : false;
     
    myboard[4][x] = (digitalRead(IN_E1) == HIGH) ? true : false;
     
    myboard[4][x+4] = (digitalRead(IN_E2) == HIGH) ? true : false;
     
    myboard[5][x] = (digitalRead(IN_F1) == HIGH) ? true : false;
     
    myboard[5][x+4] = (digitalRead(IN_F2) == HIGH) ? true : false;
     
    myboard[6][x] = (digitalRead(IN_G1) == HIGH) ? true : false;
     
    myboard[6][x+4] = (digitalRead(IN_G2) == HIGH) ? true : false;
     
    myboard[7][x] = (digitalRead(IN_H1) == HIGH) ? true : false;
     
    myboard[7][x+4] = (digitalRead(IN_H2) == HIGH) ? true : false;
     
  }

}

/*
 *  This function prints a board, for testing purposes
 */
void printBoard(){

  for(int y=0; y<8; y++){
    for(int x=0; x<8; x++){
      if( myboard[y][x] ) Serial.print("1 ");
      else Serial.print("0 ");
    }
    Serial.print("\n");
  }	
}

/*
 *Returns srow-scol-drow-dcol as a 4-digit number
 */
int32_t get_move() {
  
    Serial.print("Called get_move()\n");
    int32_t state1_flag = 0, state2_flag = 0, state3_flag = 0;
    bool state0[8][8], state1[8][8], state2[8][8], state3[8][8];
        
    getBoard();
    copy_board(state0, myboard);
    
    //delay(500);
    //Serial.println("Myboard:\n");
    printBoard();
    
    
    while(1) {

        delay(500);
        getBoard();
       // if(too_many_pieces())
            //get_move();
        
        if(!(state1_flag = diff(myboard, state0)))
            continue; //user retracted piece
        if(state1_flag) {
            Serial.print("State1:\n");
            //printBoard();
            Serial.print(state1_flag);
            copy_board(state1, myboard);
            break;
        }
    }
   
    while(1) {
      
         delay(500);
         getBoard();
         
         //if(!diff(myboard, state0))
             //return get_move(); //user retracted piece
         if((state2_flag = diff(myboard, state1))) {
             Serial.print("State2:\n");
             //printBoard();
             Serial.print(state2_flag);
             break;
         }
     }
     
     if(state2_flag > 0) { 
         Serial.println("Choose between MOVE and CASTLING");
         // CASTLING: returns negative 8-digit number
         // (negative) k_srow, k_scol, k_drow, k_dcol, r_srow, r_scol, r_drow, r_dcol
         if(get_button() == CASTLING) {
             Serial.print("Chose Castling\n");
             Serial.print((abs(state1_flag)*100 + state2_flag)*10000);
             Serial.println();
             return (-1)*((abs(state1_flag)*100 + state2_flag)*10000 + get_move());
         } 
         //MOVE without capture
         else
             return abs(state1_flag)*100 + state2_flag;
     }
     
     else {
         copy_board(state2, myboard);
     }
    
      while(1) {
        
          getBoard();
          //if(!diff(myboard, state0))
             // return get_move();
          if((state3_flag = diff(myboard, state2))) {
              Serial.print("State3:\n");
              printBoard();
              Serial.print(state3_flag);
              copy_board(state3, myboard);
              break;
          }
     }  
     
     while( get_button() != NEWMOVE )        
         get_button();
     
     //EN PASSANT: returns positive 8-digit number  
     //1, 0, srow, scol, drow, dcol, captured_row, captured_col
     if(state3_flag != abs(state1_flag)) 
         return 10000000 + abs(state2_flag)*10000 + state3_flag*100 + abs(state1_flag);
         
     //MOVE with CAPTURE
     return abs(state2_flag)*100 + state3_flag; 
     
}


/*Returns row-col as a 2-digit number
 *return value is - if piece has been removed
 *return value is + if piece has been added
 */ 
int diff(bool new_state[][8], bool old_state[][8])  {
  
  for(int i = 0; i < 8; i++){
    for(int j = 0; j < 8; j++){
      if(old_state[i][j] != new_state[i][j]) {
        if(new_state[i][j] == false)
          return (i*10 + j)*(-1);
        else
          return (i*10 + j);
      }
    }
  }

  return 0;
}  

void copy_board(bool dest[][8], bool src[][8]) {
  
    for(int y=0; y<8; y++){
        for(int x=0; x<8; x++){
            dest[y][x] = src[y][x];
        }
    }
}
   

bool too_many_pieces() {

  int count = 0;
  for(int i = 0; i < 8; i++){
      for(int j = 0; j < 8; j++){
          if(myboard[i][j]) {
              count++;
          }
      }
  }
  
  if(count > NUM_PIECES_LEFT)
      return true;
  
  return false;  
}


